package top.syfy.jwt.jwtdemo.interceptor;

import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import top.syfy.jwt.jwtdemo.exception.CustomerException;
import top.syfy.jwt.jwtdemo.exception.TokenIllegalException;
import top.syfy.jwt.jwtdemo.exception.TokenMisMatchException;
import top.syfy.jwt.jwtdemo.jwt.JwtProvide;
import top.syfy.jwt.jwtdemo.message.CodeEnum;
import top.syfy.jwt.jwtdemo.util.TokenUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * 登录拦截器 - 判断用户是否登录的拦截器
 * LoginInterceptor 拦截器类，主要作用：判断用户的登录状态，判断用户的令牌是否合法，判断用户令牌是否已达刷新标准
 * （此处：刷新令牌的手段，采用的是后端根据时间自动完成刷新"令牌交换"， 当然也可以前端调用接口来完成刷新）
 *
 * @author syfy
 * @date 2021/03/05
 */
public class LoginInterceptor implements HandlerInterceptor {

	private static final Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);

	@Autowired
	private JwtProvide jwtProvide;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
		response.setCharacterEncoding("UTF-8");
		response.setHeader("Content-Type", "text/html;charset=UTF-8");
		/*
		    从HTTP请求头中获取令牌信息
		 */
		String token = TokenUtil.getTokenFromReqHeader(request);
		/*
		    验证令牌
		 */
		try {
			jwtProvide.verifyToken(token);
			/*
			    判断令牌是否需要刷新
			 */
			String newToken = jwtProvide.refreshToken(token);
			if (!Objects.equals(token, newToken)) {
				response.setHeader("Authorization", newToken);
			}
		} catch (TokenExpiredException e) {
			logger.error("Token checkout processing : TokenExpiredException - {}", e.getLocalizedMessage());
			throw new CustomerException(CodeEnum.EXPIRED_TOKEN);
		} catch (JWTDecodeException e) {
			logger.error("Token checkout processing : JWTDecodeException - {}", e.getLocalizedMessage());
			throw new CustomerException(CodeEnum.DATA_PARSE_ERROR);
		} catch (AlgorithmMismatchException e) {
			logger.error("Token checkout processing : AlgorithmMismatchException - {}", e.getLocalizedMessage());
			throw new CustomerException(CodeEnum.ILLEGAL_TOKEN);
		} catch (SignatureVerificationException e) {
			logger.error("Token checkout processing : SignatureVerificationException - {}", e.getLocalizedMessage());
			throw new CustomerException(CodeEnum.ILLEGAL_TOKEN);
		} catch (TokenIllegalException e) {
			logger.error("Token checkout processing : TokenIllegalException - {}", e.getLocalizedMessage());
			throw new CustomerException(CodeEnum.ILLEGAL_TOKEN);
		} catch (TokenMisMatchException e) {
			logger.error("Token checkout processing : TokenMisMatchException - {}", e.getLocalizedMessage());
			throw new CustomerException(CodeEnum.ILLEGAL_TOKEN);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("Token checkout processing : Unknown Exception - {}", e.getLocalizedMessage());
			throw new CustomerException(CodeEnum.UNKNOWN_ERROR);
		}
		return true;
	}
}
